package com.tianji.learning.service.impl;

// ... 略
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.enums.PointsRecordType;
import com.tianji.learning.domain.po.PointsRecord;
import com.tianji.learning.mapper.PointsRecordMapper;
import com.tianji.learning.service.IPointsRecordService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

import static com.tianji.common.utils.DateUtils.SIGN_DATE_SUFFIX_FORMATTER;
import static com.tianji.learning.constans.RedisConstants.POINTS_BOARDS_KEY_PREFIX;

/**
 * <p>
 * 学习积分记录，每个月底清零 服务实现类
 * </p>
 */
@Service
@RequiredArgsConstructor
public class PointsRecordServiceImpl extends ServiceImpl<PointsRecordMapper, PointsRecord> implements IPointsRecordService {
    private final StringRedisTemplate RedisTemplate;
    @Override
    public void addPointsRecord(Long userId, int points, PointsRecordType type) {
        // 1、判断当前积分类型是否有上限
        int maxPoints = type.getMaxPoints();  // 50
        if (maxPoints > 0) {
            // 2、如果有，则判断当天该用户通过该渠道 已获取积分是否超过每日上限
            // 2.1、查询【当前用户】【今日】通过该【积分类型】已获取【积分总数】
            // select sum(points) from points_record where user_id = ? and `type` = ? and create_time between ? and ?
            int currentDayPoints = queryCurrentDayPoints(userId, type);  // 45

            // 2.2、判断是否超过了每日上限
            if (currentDayPoints >= maxPoints) {
                // 2.3、超过直接结束
                return;
            }

            // 2.3、处理 已有积分 + 本次待加积分 > 积分上限的情况，不能直接加了，而是要加上：上限 - 已有积分的 差值部分
            if (currentDayPoints + points > maxPoints) {
                points = maxPoints - currentDayPoints;
            }
        }
        // 3、如果没有，直接保存积分记录
        PointsRecord pointsRecord = new PointsRecord().setPoints(points).setUserId(userId).setType(type.getValue());
        save(pointsRecord);

        //4. 更新总积分到redis
        String key = POINTS_BOARDS_KEY_PREFIX+LocalDateTime.now().format(SIGN_DATE_SUFFIX_FORMATTER);
        RedisTemplate.opsForZSet().incrementScore(key, UserContext.getUser().toString(), points);
    }



    private int queryCurrentDayPoints(Long userId, PointsRecordType type) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime begin = DateUtils.getDayStartTime(now);
        LocalDateTime end = DateUtils.getDayEndTime(now);

        LambdaQueryWrapper<PointsRecord> queryWrapper = Wrappers.<PointsRecord>lambdaQuery()
                .eq(PointsRecord::getUserId,userId)
                .eq(PointsRecord::getType,type)
                .between(PointsRecord::getCreateTime,begin,end);

        return this.getBaseMapper().queryCurrentDayPoints(queryWrapper);
    }

    private int queryCurrentDayPoints2(Long userId, PointsRecordType type) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime begin = DateUtils.getDayStartTime(now);
        LocalDateTime end = DateUtils.getDayEndTime(now);
        PointsRecord record = this.query()
                .select("sum(points) as points")
                .eq("user_id", userId)
                .eq("`type`", type)
                .between("create_time", begin, end)
                .one();
        return ObjectUtils.isEmpty(record) || ObjectUtils.isEmpty(record.getPoints()) ? 0 : record.getPoints();
    }
}